home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / Python 1.3 / source code / Modules / tkintermodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-17  |  26.2 KB  |  1,293 lines  |  [TEXT/R*ch]

  1. /* tkintermodule.c -- Interface to libtk.a and libtcl.a.
  2.    Copyright (C) 1994 Steen Lumholt */
  3.  
  4. #include "Python.h"
  5.  
  6. #ifdef macintosh
  7. #define MAC_TCL
  8. #endif
  9.  
  10. #ifdef MAC_TCL
  11. #define WITH_APPINIT
  12. #endif
  13.  
  14. #define PyInit_tkinter inittkinter
  15.  
  16. #include <tcl.h>
  17. #include <tk.h>
  18.  
  19. extern char *getprogramname ();
  20.  
  21. /* Internal declarations from tkInt.h.  */
  22. #if (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION) >= 4001
  23. extern int Tk_GetNumMainWindows();
  24. #else
  25. extern int tk_NumMainWindows;
  26. #define Tk_GetNumMainWindows() (tk_NumMainWindows)
  27. #endif
  28.  
  29. #if TK_MAJOR_VERSION < 4
  30. extern struct { Tk_Window win; } *tkMainWindowList;
  31. #endif
  32.  
  33. /**** Tkapp Object Declaration ****/
  34.  
  35. staticforward PyTypeObject Tkapp_Type;
  36.  
  37. typedef struct
  38.   {
  39.     PyObject_HEAD
  40.     Tcl_Interp *interp;
  41.     Tk_Window tkwin;
  42.   }
  43. TkappObject;
  44.  
  45. #define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
  46. #define Tkapp_Tkwin(v)  (((TkappObject *) (v))->tkwin)
  47. #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
  48. #define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
  49.  
  50. #define DEBUG_REFCNT(v) (printf ("DEBUG: id=%p, refcnt=%i\n", \
  51.                  (void *) v, ((PyObject *) v)->ob_refcnt))
  52.  
  53. /**** Error Handling ****/
  54.  
  55. static PyObject *Tkinter_TclError;
  56. static int quitMainLoop = 0;
  57. static int errorInCmd = 0;
  58. static PyObject *excInCmd;
  59. static PyObject *valInCmd;
  60. static PyObject *trbInCmd;
  61.  
  62. static PyObject *
  63. Tkinter_Error (v)
  64.      PyObject *v;
  65. {
  66.   PyErr_SetString (Tkinter_TclError, Tkapp_Result (v));
  67.   return NULL;
  68. }
  69.  
  70. int
  71. PythonCmd_Error (interp)
  72.      Tcl_Interp *interp;
  73. {
  74.   errorInCmd = 1;
  75.   PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
  76.   return TCL_ERROR;
  77. }
  78.  
  79. /**** Utils ****/
  80.  
  81. static char *
  82. AsString (value, tmp)
  83.      PyObject *value;
  84.      PyObject *tmp;
  85. {
  86.   if (PyString_Check (value))
  87.     return PyString_AsString (value);
  88.   else
  89.     {
  90.       PyObject *v;
  91.  
  92.       v = PyObject_Str (value);
  93.       PyList_Append (tmp, v);
  94.       Py_DECREF (v);
  95.       return PyString_AsString (v);
  96.     }
  97. }
  98.  
  99. #define ARGSZ 64
  100.  
  101. static char *
  102. Merge (args)
  103.      PyObject *args;
  104. {
  105.   PyObject *tmp;
  106.   char *argvStore[ARGSZ];
  107.   char **argv;
  108.   int fvStore[ARGSZ];
  109.   int *fv;
  110.   int argc;
  111.   char *res;
  112.   int i;
  113.  
  114.   tmp = PyList_New (0);
  115.   argv = argvStore;
  116.   fv = fvStore;
  117.  
  118.   if (!PyTuple_Check (args))
  119.     {
  120.       argc = 1;
  121.       fv[0] = 0;
  122.       argv[0] = AsString (args, tmp);
  123.     }
  124.   else
  125.     {
  126.       PyObject *v;
  127.  
  128.       if (PyTuple_Size (args) > ARGSZ)
  129.     {
  130.       argv = (char **) malloc (PyTuple_Size (args) * sizeof (char *));
  131.       fv = (int *) malloc (PyTuple_Size (args) * sizeof (int));
  132.       if (argv == NULL || fv == NULL)
  133.         PyErr_NoMemory ();
  134.     }
  135.  
  136.       argc = PyTuple_Size (args);
  137.       for (i = 0; i < argc; i++)
  138.     {
  139.       v = PyTuple_GetItem (args, i);
  140.       if (PyTuple_Check (v))
  141.         {
  142.           fv[i] = 1;
  143.           argv[i] = Merge (v);
  144.         }
  145.       else if (v == Py_None)
  146.         {
  147.           argc = i;
  148.           break;
  149.         }
  150.       else
  151.         {
  152.           fv[i] = 0;
  153.           argv[i] = AsString (v, tmp);
  154.         }
  155.     }
  156.     }
  157.  
  158.   res = Tcl_Merge (argc, argv);
  159.  
  160.   Py_DECREF (tmp);
  161.   for (i = 0; i < argc; i++)
  162.     if (fv[i]) free (argv[i]);
  163.   if (argv != argvStore)
  164.     free (argv);
  165.   if (fv != fvStore)
  166.     free (fv);
  167.  
  168.   return res;
  169. }
  170.  
  171. static PyObject *
  172. Split (self, list)
  173.      PyObject *self;
  174.      char *list;
  175. {
  176.   int argc;
  177.   char **argv;
  178.   PyObject *v;
  179.  
  180.   if (list == NULL)
  181.     {
  182.       Py_INCREF (Py_None);
  183.       return Py_None;
  184.     }
  185.  
  186.   if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
  187.     return Tkinter_Error (self);
  188.  
  189.   if (argc == 0)
  190.     v = PyString_FromString ("");
  191.   else if (argc == 1)
  192.     v = PyString_FromString (argv[0]);
  193.   else
  194.     {
  195.       int i;
  196.  
  197.       v = PyTuple_New (argc);
  198.       for (i = 0; i < argc; i++)
  199.     PyTuple_SetItem (v, i, Split (self, argv[i]));
  200.     }
  201.  
  202.   free (argv);
  203.   return v;
  204. }
  205.  
  206. /**** Tkapp Object ****/
  207.  
  208. #ifndef WITH_APPINIT
  209. int
  210. Tcl_AppInit (interp)
  211.      Tcl_Interp *interp;
  212. {
  213.     Tk_Window main;
  214.     main = Tk_MainWindow(interp);
  215.   if (Tcl_Init (interp) == TCL_ERROR) {
  216.     fprintf(stderr, "Tcl_Init error: %s\n", interp->result);
  217.     return TCL_ERROR;
  218.   }
  219.   if (Tk_Init (interp) == TCL_ERROR) {
  220.     fprintf(stderr, "Tk_Init error: %s\n", interp->result);
  221.     return TCL_ERROR;
  222.   }
  223.   return TCL_OK;
  224. }
  225. #endif /* !WITH_APPINIT */
  226.  
  227. /* Initialize the Tk application; see the `main' function in
  228.    `tkMain.c'.  */
  229. static TkappObject *
  230. Tkapp_New (screenName, baseName, className, interactive)
  231.      char *screenName;
  232.      char *baseName;
  233.      char *className;
  234.      int interactive;
  235. {
  236.   TkappObject *v;
  237.   
  238.   v = PyObject_NEW (TkappObject, &Tkapp_Type);
  239.   if (v == NULL)
  240.     return NULL;
  241.  
  242.   v->interp = Tcl_CreateInterp ();
  243.   v->tkwin = Tk_CreateMainWindow (v->interp, screenName, 
  244.                   baseName, className);
  245.   if (v->tkwin == NULL)
  246.     return (TkappObject *) Tkinter_Error ((PyObject *) v);
  247.  
  248.   Tk_GeometryRequest (v->tkwin, 200, 200);
  249.  
  250.   if (screenName != NULL)
  251.     Tcl_SetVar2 (v->interp, "env", "DISPLAY", screenName, TCL_GLOBAL_ONLY);
  252.  
  253.   if (interactive)
  254.     Tcl_SetVar (v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
  255.   else
  256.     Tcl_SetVar (v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
  257.  
  258.   if (Tcl_AppInit (v->interp) != TCL_OK)
  259.     {
  260.       PyErr_SetString (Tkinter_TclError, "Tcl_AppInit failed"); /* XXX */
  261.       return NULL;
  262.     }
  263.  
  264.   return v;
  265. }
  266.  
  267. /** Tcl Eval **/
  268.  
  269. static PyObject *
  270. Tkapp_Call (self, args)
  271.      PyObject *self;
  272.      PyObject *args;
  273. {
  274.   char *cmd;
  275.  
  276.   cmd = Merge (args);
  277.   if (Tcl_Eval (Tkapp_Interp (self), cmd) == TCL_ERROR)
  278.     {
  279.       free (cmd);
  280.       return Tkinter_Error (self);
  281.     }
  282.  
  283.   free (cmd);
  284.   return PyString_FromString (Tkapp_Result (self));
  285. }
  286.  
  287. static PyObject *
  288. Tkapp_GlobalCall (self, args)
  289.      PyObject *self;
  290.      PyObject *args;
  291. {
  292.   char *cmd;
  293.  
  294.   cmd = Merge (args);
  295.   if (Tcl_GlobalEval (Tkapp_Interp (self), cmd) == TCL_ERROR)
  296.     {
  297.       free (cmd);
  298.       return Tkinter_Error (self);
  299.     }
  300.   
  301.   free (cmd);
  302.   return PyString_FromString (Tkapp_Result (self));
  303. }
  304.  
  305. static PyObject *
  306. Tkapp_Eval (self, args)
  307.      PyObject *self;
  308.      PyObject *args;
  309. {
  310.   char *script;
  311.   
  312.   if (!PyArg_Parse (args, "s", &script))
  313.     return NULL;
  314.  
  315.   if (Tcl_Eval (Tkapp_Interp (self), script) == TCL_ERROR)
  316.     return Tkinter_Error (self);
  317.   
  318.   return PyString_FromString (Tkapp_Result (self));
  319. }
  320.  
  321. static PyObject *
  322. Tkapp_GlobalEval (self, args)
  323.      PyObject *self;
  324.      PyObject *args;
  325. {
  326.   char *script;
  327.   
  328.   if (!PyArg_Parse (args, "s", &script))
  329.     return NULL;
  330.  
  331.   if (Tcl_GlobalEval (Tkapp_Interp (self), script) == TCL_ERROR)
  332.     return Tkinter_Error (self);
  333.  
  334.   return PyString_FromString (Tkapp_Result (self));
  335. }
  336.  
  337. static PyObject *
  338. Tkapp_EvalFile (self, args)
  339.      PyObject *self;
  340.      PyObject *args;
  341. {
  342.   char *fileName;
  343.  
  344.   if (!PyArg_Parse (args, "s", &fileName))
  345.     return NULL;
  346.  
  347.   if (Tcl_EvalFile (Tkapp_Interp (self), fileName) == TCL_ERROR)
  348.     return Tkinter_Error (self);
  349.  
  350.   return PyString_FromString (Tkapp_Result (self));
  351. }
  352.  
  353. static PyObject *
  354. Tkapp_Record (self, args)
  355.      PyObject *self;
  356.      PyObject *args;
  357. {
  358.   char *script;
  359.  
  360.   if (!PyArg_Parse (args, "s", &script))
  361.     return NULL;
  362.  
  363.   if (Tcl_RecordAndEval (Tkapp_Interp (self), 
  364.              script, TCL_NO_EVAL) == TCL_ERROR)
  365.     return Tkinter_Error (self);
  366.  
  367.   return PyString_FromString (Tkapp_Result (self));
  368. }
  369.  
  370. static PyObject *
  371. Tkapp_AddErrorInfo (self, args)
  372.      PyObject *self;
  373.      PyObject *args;
  374. {
  375.   char *msg;
  376.  
  377.   if (!PyArg_Parse (args, "s", &msg))
  378.     return NULL;
  379.   Tcl_AddErrorInfo (Tkapp_Interp (self), msg);
  380.  
  381.   Py_INCREF(Py_None);
  382.   return Py_None;
  383. }
  384.  
  385. /** Tcl Variable **/
  386.  
  387. static PyObject *
  388. SetVar (self, args, flags)
  389.      PyObject *self;
  390.      PyObject *args;
  391.      int flags;
  392. {
  393.   char *name1, *name2, *ok;
  394.   PyObject *newValue;
  395.   PyObject *tmp;
  396.  
  397.   tmp = PyList_New (0);
  398.  
  399.   if (PyArg_Parse (args, "(sO)", &name1, &newValue))
  400.     ok = Tcl_SetVar (Tkapp_Interp (self), name1, 
  401.              AsString (newValue, tmp), flags); /* XXX Merge? */
  402.   else if (PyArg_Parse (args, "(ssO)", &name1, &name2, &newValue))
  403.     ok = Tcl_SetVar2 (Tkapp_Interp (self), name1, name2, 
  404.               AsString (newValue, tmp), flags);
  405.   else
  406.     {
  407.       Py_DECREF (tmp);
  408.       return NULL;
  409.     }
  410.   Py_DECREF (tmp);
  411.  
  412.   if (!ok)
  413.     return Tkinter_Error (self);
  414.  
  415.   Py_INCREF (Py_None);
  416.   return Py_None;
  417. }
  418.  
  419. static PyObject *
  420. Tkapp_SetVar (self, args)
  421.      PyObject *self;
  422.      PyObject *args;
  423. {
  424.   return SetVar (self, args, TCL_LEAVE_ERR_MSG);
  425. }
  426.  
  427. static PyObject *
  428. Tkapp_GlobalSetVar (self, args)
  429.      PyObject *self;
  430.      PyObject *args;
  431. {
  432.   return SetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  433. }
  434.  
  435. static PyObject *
  436. GetVar (self, args, flags)
  437.      PyObject *self;
  438.      PyObject *args;
  439.      int flags;
  440. {
  441.   char *name1, *name2, *s;
  442.  
  443.   if (PyArg_Parse (args, "s", &name1))
  444.     s = Tcl_GetVar (Tkapp_Interp (self), name1, flags);
  445.   else if (PyArg_Parse (args, "(ss)", &name1, &name2))
  446.     s = Tcl_GetVar2 (Tkapp_Interp (self), name1, name2, flags);
  447.   else
  448.     return NULL;
  449.  
  450.   if (s == NULL)
  451.     return Tkinter_Error (self);
  452.  
  453.   return PyString_FromString (s);
  454. }
  455.  
  456. static PyObject *
  457. Tkapp_GetVar (self, args)
  458.      PyObject *self;
  459.      PyObject *args;
  460. {
  461.   return GetVar (self, args, TCL_LEAVE_ERR_MSG);
  462. }
  463.  
  464. static PyObject *
  465. Tkapp_GlobalGetVar (self, args)
  466.      PyObject *self;
  467.      PyObject *args;
  468. {
  469.   return GetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  470. }
  471.  
  472. static PyObject *
  473. UnsetVar (self, args, flags)
  474.      PyObject *self;
  475.      PyObject *args;
  476.      int flags;
  477. {
  478.   char *name1, *name2;
  479.   int code;
  480.  
  481.   if (PyArg_Parse (args, "s", &name1))
  482.     code = Tcl_UnsetVar (Tkapp_Interp (self), name1, flags);
  483.   else if (PyArg_Parse (args, "(ss)", &name1, &name2))
  484.     code = Tcl_UnsetVar2 (Tkapp_Interp (self), name1, name2, flags);
  485.   else
  486.     return NULL;
  487.  
  488.   if (code == TCL_ERROR)
  489.     return Tkinter_Error (self);
  490.  
  491.   Py_INCREF (Py_None);
  492.   return Py_None;
  493. }
  494.  
  495. static PyObject *
  496. Tkapp_UnsetVar (self, args)
  497.      PyObject *self;
  498.      PyObject *args;
  499. {
  500.   return UnsetVar (self, args, TCL_LEAVE_ERR_MSG);
  501. }
  502.  
  503. static PyObject *
  504. Tkapp_GlobalUnsetVar (self, args)
  505.      PyObject *self;
  506.      PyObject *args;
  507. {
  508.   return UnsetVar (self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
  509. }
  510.  
  511. /** Tcl to Python **/
  512.  
  513. static PyObject *
  514. Tkapp_GetInt (self, args)
  515.      PyObject *self;
  516.      PyObject *args;
  517. {
  518.   char *s;
  519.   int v;
  520.  
  521.   if (!PyArg_Parse (args, "s", &s))
  522.     return NULL;
  523.   if (Tcl_GetInt (Tkapp_Interp (self), s, &v) == TCL_ERROR)
  524.     return Tkinter_Error (self);
  525.   return Py_BuildValue ("i", v);
  526. }
  527.  
  528. static PyObject *
  529. Tkapp_GetDouble (self, args)
  530.      PyObject *self;
  531.      PyObject *args;
  532. {
  533.   char *s;
  534.   double v;
  535.  
  536.   if (!PyArg_Parse (args, "s", &s))
  537.     return NULL;
  538.   if (Tcl_GetDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
  539.     return Tkinter_Error (self);
  540.   return Py_BuildValue ("d", v);
  541. }
  542.  
  543. static PyObject *
  544. Tkapp_GetBoolean (self, args)
  545.      PyObject *self;
  546.      PyObject *args;
  547. {
  548.   char *s;
  549.   int v;
  550.  
  551.   if (!PyArg_Parse (args, "s", &s))
  552.     return NULL;
  553.   if (Tcl_GetBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
  554.     return Tkinter_Error (self);
  555.   return Py_BuildValue ("i", v);
  556. }
  557.  
  558. static PyObject *
  559. Tkapp_ExprString (self, args)
  560.      PyObject *self;
  561.      PyObject *args;
  562. {
  563.   char *s;
  564.  
  565.   if (!PyArg_Parse (args, "s", &s))
  566.     return NULL;
  567.   if (Tcl_ExprString (Tkapp_Interp (self), s) == TCL_ERROR)
  568.     return Tkinter_Error (self);
  569.   return Py_BuildValue ("s", Tkapp_Result (self));
  570. }
  571.  
  572. static PyObject *
  573. Tkapp_ExprLong (self, args)
  574.      PyObject *self;
  575.      PyObject *args;
  576. {
  577.   char *s;
  578.   long v;
  579.  
  580.   if (!PyArg_Parse (args, "s", &s))
  581.     return NULL;
  582.   if (Tcl_ExprLong (Tkapp_Interp (self), s, &v) == TCL_ERROR)
  583.     return Tkinter_Error (self);
  584.   return Py_BuildValue ("l", v);
  585. }
  586.  
  587. static PyObject *
  588. Tkapp_ExprDouble (self, args)
  589.      PyObject *self;
  590.      PyObject *args;
  591. {
  592.   char *s;
  593.   double v;
  594.  
  595.   if (!PyArg_Parse (args, "s", &s))
  596.     return NULL;
  597.   if (Tcl_ExprDouble (Tkapp_Interp (self), s, &v) == TCL_ERROR)
  598.     return Tkinter_Error (self);
  599.   return Py_BuildValue ("d", v);
  600. }
  601.  
  602. static PyObject *
  603. Tkapp_ExprBoolean (self, args)
  604.      PyObject *self;
  605.      PyObject *args;
  606. {
  607.   char *s;
  608.   int v;
  609.  
  610.   if (!PyArg_Parse (args, "s", &s))
  611.     return NULL;
  612.   if (Tcl_ExprBoolean (Tkapp_Interp (self), s, &v) == TCL_ERROR)
  613.     return Tkinter_Error (self);
  614.   return Py_BuildValue ("i", v);
  615. }
  616.  
  617. static PyObject *
  618. Tkapp_SplitList (self, args)
  619.      PyObject *self;
  620.      PyObject *args;
  621. {
  622.   char *list;
  623.   int argc;
  624.   char **argv;
  625.   PyObject *v;
  626.   int i;
  627.  
  628.   if (!PyArg_Parse (args, "s", &list))
  629.     return NULL;
  630.  
  631.   if (Tcl_SplitList (Tkapp_Interp (self), list, &argc, &argv) == TCL_ERROR)
  632.     return Tkinter_Error (self);
  633.  
  634.   v = PyTuple_New (argc);
  635.   for (i = 0; i < argc; i++)
  636.     PyTuple_SetItem (v, i, PyString_FromString (argv[i]));
  637.  
  638.   free (argv);
  639.   return v;
  640. }
  641.  
  642. static PyObject *
  643. Tkapp_Split (self, args)
  644.      PyObject *self;
  645.      PyObject *args;
  646. {
  647.   char *list;
  648.  
  649.   if (!PyArg_Parse (args, "s", &list))
  650.     return NULL;
  651.   return Split (self, list);
  652. }
  653.  
  654. static PyObject *
  655. Tkapp_Merge (self, args)
  656.      PyObject *self;
  657.      PyObject *args;
  658. {
  659.   char *s;
  660.   PyObject *v;
  661.  
  662.   s = Merge (args);
  663.   v = PyString_FromString (s);
  664.   free (s);
  665.   return v;
  666. }
  667.  
  668. /** Tcl Command **/
  669.  
  670. /* This is the Tcl command that acts as a wrapper for Python
  671.    function or method.  */
  672. static int
  673. PythonCmd (clientData, interp, argc, argv)
  674.      ClientData clientData;    /* Is (self, func) */
  675.      Tcl_Interp *interp;
  676.      int argc;
  677.      char *argv[];
  678. {
  679.   PyObject *self, *func, *arg, *res, *tmp;
  680.   int i;
  681.  
  682.   self = PyTuple_GetItem ((PyObject *) clientData, 0);
  683.   func = PyTuple_GetItem ((PyObject *) clientData, 1);
  684.  
  685.   /* Create argument list (argv1, ..., argvN) */
  686.   arg = PyTuple_New (argc - 1);
  687.   for (i = 0; i < (argc - 1); i++)
  688.     PyTuple_SetItem (arg, i, PyString_FromString (argv[i + 1]));
  689.   
  690.   res = PyEval_CallObject (func, arg);
  691.   Py_DECREF (arg);
  692.  
  693.   if (res == NULL)
  694.     return PythonCmd_Error (interp);
  695.  
  696.   tmp = PyList_New (0);
  697.   Tcl_SetResult (Tkapp_Interp (self), AsString (res, tmp), TCL_VOLATILE);
  698.   Py_DECREF (res);
  699.   Py_DECREF (tmp);
  700.  
  701.   return TCL_OK;
  702. }
  703.  
  704. static void
  705. PythonCmdDelete (clientData)
  706.      ClientData clientData;    /* Is (self, func) */
  707. {
  708.   Py_DECREF ((PyObject *) clientData);
  709. }
  710.  
  711. static PyObject *
  712. Tkapp_CreateCommand (self, args)
  713.      PyObject *self;
  714.      PyObject *args;
  715. {
  716.   char *cmdName;
  717.   PyObject *data;
  718.   PyObject *func;
  719.   
  720.   /* Args is: (cmdName, func) */
  721.   if (!PyTuple_Check (args) 
  722.       || !(PyTuple_Size (args) == 2)
  723.       || !PyString_Check (PyTuple_GetItem (args, 0))
  724.       || !PyCallable_Check (PyTuple_GetItem (args, 1)))
  725.     {
  726.       PyErr_SetString (PyExc_TypeError, "bad argument list");
  727.       return NULL;
  728.     }
  729.  
  730.   cmdName = PyString_AsString (PyTuple_GetItem (args, 0));
  731.   func = PyTuple_GetItem (args, 1);
  732.  
  733.   data = PyTuple_New (2);   /* ClientData is: (self, func) */
  734.  
  735.   Py_INCREF (self);
  736.   PyTuple_SetItem (data, 0, self);
  737.  
  738.   Py_INCREF (func);
  739.   PyTuple_SetItem (data, 1, func);
  740.  
  741.   Tcl_CreateCommand (Tkapp_Interp (self), cmdName, PythonCmd,
  742.              (ClientData) data, PythonCmdDelete);
  743.  
  744.   Py_INCREF (Py_None);
  745.   return Py_None;
  746. }
  747.  
  748. static PyObject *
  749. Tkapp_DeleteCommand (self, args)
  750.      PyObject *self;
  751.      PyObject *args;
  752. {
  753.   char *cmdName;
  754.  
  755.   if (!PyArg_Parse (args, "s", &cmdName))
  756.     return NULL;
  757.   if (Tcl_DeleteCommand (Tkapp_Interp (self), cmdName) == -1)
  758.     {
  759.       PyErr_SetString (Tkinter_TclError, "can't delete Tcl command");
  760.       return NULL;
  761.     }
  762.   Py_INCREF (Py_None);
  763.   return Py_None;
  764. }
  765.  
  766. /** File Handler **/
  767.  
  768. static void
  769. FileHandler (clientData, mask)
  770.      ClientData clientData;    /* Is: (func, file) */
  771.      int mask;
  772. {
  773.   PyObject *func, *file, *arg, *res;
  774.  
  775.   func = PyTuple_GetItem ((PyObject *) clientData, 0);
  776.   file = PyTuple_GetItem ((PyObject *) clientData, 1);
  777.  
  778.   arg = Py_BuildValue ("(Oi)", file, (long) mask);
  779.   res = PyEval_CallObject (func, arg);
  780.   Py_DECREF (arg);
  781.   if (res == NULL)
  782.     {
  783.       errorInCmd = 1;
  784.       PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
  785.     }
  786.   Py_XDECREF (res);
  787. }
  788.  
  789. static int
  790. GetFileNo (file)
  791.     PyObject *file; /* Either an int >= 0 or an object with a
  792.                .fileno() method that returns an int >= 0 */
  793. {
  794.     PyObject *meth, *args, *res;
  795.     int id;
  796.     if (PyInt_Check(file)) {
  797.         id = PyInt_AsLong(file);
  798.         if (id < 0)
  799.             PyErr_SetString(PyExc_ValueError, "invalid file id");
  800.         return id;
  801.     }
  802.     meth = PyObject_GetAttrString(file, "fileno");
  803.     if (meth == NULL)
  804.         return -1;
  805.     args = PyTuple_New(0);
  806.     if (args == NULL)
  807.         return -1;
  808.     res = PyEval_CallObject(meth, args);
  809.     Py_DECREF(args);
  810.     Py_DECREF(meth);
  811.     if (res == NULL)
  812.         return -1;
  813.     if (PyInt_Check(res))
  814.         id = PyInt_AsLong(res);
  815.     else
  816.         id = -1;
  817.     if (id < 0)
  818.         PyErr_SetString(PyExc_ValueError,
  819.                 "invalid fileno() return value");
  820.     Py_DECREF(res);
  821.     return id;
  822. }
  823.  
  824. static PyObject *
  825. Tkapp_CreateFileHandler (self, args)
  826.      PyObject *self;
  827.      PyObject *args;        /* Is (file, mask, func) */
  828. {
  829.   PyObject *file, *func, *data;
  830.   int mask, id;
  831.  
  832.   if (!PyArg_Parse (args, "(OiO)", &file, &mask, &func))
  833.     return NULL;
  834.   id = GetFileNo (file);
  835.   if (id < 0)
  836.     return NULL;
  837.   if (!PyCallable_Check(func))
  838.     {
  839.       PyErr_SetString (PyExc_TypeError, "bad argument list");
  840.       return NULL;
  841.     }
  842.  
  843.   /* ClientData is: (func, file) */
  844.   data = Py_BuildValue ("(OO)", func, file);
  845.  
  846.   Tk_CreateFileHandler (id, mask, FileHandler, (ClientData) data);
  847.   /* XXX fileHandlerDict */
  848.  
  849.   Py_INCREF (Py_None);
  850.   return Py_None;
  851. }
  852.  
  853. static PyObject *
  854. Tkapp_DeleteFileHandler (self, args)
  855.      PyObject *self;
  856.      PyObject *args;        /* Args: file */
  857. {
  858.   PyObject *file;
  859.   int id;
  860.  
  861.   if (!PyArg_Parse (args, "O", &file))
  862.     return NULL;
  863.   id = GetFileNo (file);
  864.   if (id < 0)
  865.     return NULL;
  866.  
  867.   Tk_DeleteFileHandler (id);
  868.   /* XXX fileHandlerDict */
  869.   Py_INCREF (Py_None);
  870.   return Py_None;
  871. }
  872.  
  873. /**** Tktt Object (timer token) ****/
  874.  
  875. staticforward PyTypeObject Tktt_Type;
  876.  
  877. typedef struct
  878.   {
  879.     PyObject_HEAD
  880.     Tk_TimerToken token;
  881.     PyObject *func;
  882.   }
  883. TkttObject;
  884.  
  885. static PyObject *
  886. Tktt_DeleteTimerHandler (self, args)
  887.      PyObject *self;
  888.      PyObject *args;
  889. {
  890.   TkttObject *v = (TkttObject *) self;
  891.  
  892.   if (!PyArg_Parse (args, ""))
  893.     return NULL;
  894.   if (v->func != NULL)
  895.     {
  896.       Tk_DeleteTimerHandler (v->token);
  897.       PyMem_DEL (v->func);
  898.       v->func = NULL;
  899.     }
  900.   Py_INCREF (Py_None);
  901.   return Py_None;
  902. }
  903.  
  904. static PyMethodDef Tktt_methods[] =
  905. {
  906.   {"deletetimerhandler", Tktt_DeleteTimerHandler},
  907.   {NULL, NULL}
  908. };
  909.  
  910. static TkttObject *
  911. Tktt_New (token, func)
  912.      Tk_TimerToken token;
  913.      PyObject *func;
  914. {
  915.   TkttObject *v;
  916.   
  917.   v = PyObject_NEW (TkttObject, &Tktt_Type);
  918.   if (v == NULL)
  919.     return NULL;
  920.  
  921.   v->token = token;
  922.   v->func = func;
  923.   Py_INCREF (v->func);
  924.   return v;
  925. }
  926.  
  927. static void
  928. Tktt_Dealloc (self)
  929.      PyObject *self;
  930. {
  931.   PyMem_DEL (self);
  932. }
  933.  
  934. static int
  935. Tktt_Print (self, fp, flags)
  936.      PyObject *self;
  937.      FILE *fp;
  938.      int flags;
  939. {
  940.   TkttObject *v = (TkttObject *) self;
  941.  
  942.   fprintf(fp, "<tktimertoken at 0x%x%s>", v,
  943.     v->func == NULL ? ", handler deleted" : "");
  944.   return 0;
  945. }
  946.  
  947. static PyObject *
  948. Tktt_GetAttr (self, name)
  949.      PyObject *self;
  950.      char *name;
  951. {
  952.   return Py_FindMethod (Tktt_methods, self, name);
  953. }
  954.  
  955. static PyTypeObject Tktt_Type =
  956. {
  957.   PyObject_HEAD_INIT (&PyType_Type)
  958.   0,                /*ob_size */
  959.   "tktimertoken",        /*tp_name */
  960.   sizeof (TkttObject),        /*tp_basicsize */
  961.   0,                /*tp_itemsize */
  962.   Tktt_Dealloc,            /*tp_dealloc */
  963.   Tktt_Print,            /*tp_print */
  964.   Tktt_GetAttr,            /*tp_getattr */
  965.   0,                /*tp_setattr */
  966.   0,                /*tp_compare */
  967.   0,                /*tp_repr */
  968.   0,                /*tp_as_number */
  969.   0,                /*tp_as_sequence */
  970.   0,                /*tp_as_mapping */
  971.   0,                /*tp_hash */
  972. };
  973.  
  974. /** Timer Handler **/
  975.  
  976. static void
  977. TimerHandler (clientData)
  978.      ClientData clientData;
  979. {
  980.   PyObject *func = (PyObject *) clientData;
  981.   PyObject *arg, *res;
  982.  
  983.   arg = PyTuple_New (0);
  984.   res = PyEval_CallObject (func, arg);
  985.   Py_DECREF (arg);
  986.   if (res == NULL)
  987.     {
  988.       errorInCmd = 1;
  989.       PyErr_Fetch (&excInCmd, &valInCmd, &trbInCmd);
  990.     }
  991.   else
  992.     Py_DECREF (res);
  993. }
  994.  
  995. static PyObject *
  996. Tkapp_CreateTimerHandler (self, args)
  997.      PyObject *self;
  998.      PyObject *args;        /* Is (milliseconds, func) */
  999. {
  1000.   int milliseconds;
  1001.   PyObject *func;
  1002.   Tk_TimerToken token;
  1003.  
  1004.   if (!PyArg_Parse (args, "(iO)", &milliseconds, &func))
  1005.     return NULL;
  1006.   if (!PyCallable_Check(func))
  1007.     {
  1008.       PyErr_SetString (PyExc_TypeError, "bad argument list");
  1009.       return NULL;
  1010.     }
  1011.   token = Tk_CreateTimerHandler(milliseconds, TimerHandler, (ClientData) func);
  1012.   return (PyObject *) Tktt_New (token, func);
  1013. }
  1014.  
  1015. /** Event Loop **/
  1016.  
  1017. static PyObject *
  1018. Tkapp_MainLoop (self, args)
  1019.      PyObject *self;
  1020.      PyObject *args;
  1021. {
  1022.   int threshold = 0;
  1023.  
  1024.   if (!PyArg_ParseTuple (args, "|i", &threshold))
  1025.     return NULL;
  1026.  
  1027.   quitMainLoop = 0;
  1028.   while (Tk_GetNumMainWindows() > threshold && !quitMainLoop && !errorInCmd)
  1029.     {
  1030.       if (PyOS_InterruptOccurred ())
  1031.     {
  1032.       PyErr_SetNone (PyExc_KeyboardInterrupt);
  1033.       return NULL;
  1034.     }
  1035.       Tk_DoOneEvent (0);
  1036.     }
  1037.   quitMainLoop = 0;
  1038.  
  1039.   if (errorInCmd)
  1040.     {
  1041.       errorInCmd = 0;
  1042.       PyErr_Restore (excInCmd, valInCmd, trbInCmd);
  1043.       excInCmd = valInCmd = trbInCmd = NULL;
  1044.       return NULL;
  1045.     }
  1046.   Py_INCREF (Py_None);
  1047.   return Py_None;
  1048. }
  1049.  
  1050. static PyObject *
  1051. Tkapp_DoOneEvent (self, args)
  1052.     PyObject *self;
  1053.     PyObject *args;
  1054. {
  1055.     int    flags = TK_ALL_EVENTS;
  1056.     int rv;
  1057.  
  1058.     if (!PyArg_ParseTuple (args, "|i", &flags))
  1059.       return NULL;
  1060.     rv = Tk_DoOneEvent(flags);
  1061.     return Py_BuildValue ("i", rv);
  1062. }
  1063.  
  1064. static PyObject *
  1065. Tkapp_Quit (self, args)
  1066.      PyObject *self;
  1067.      PyObject *args;
  1068. {
  1069.  
  1070.   if (!PyArg_Parse (args, ""))
  1071.     return NULL;
  1072.   quitMainLoop = 1;
  1073.   Py_INCREF (Py_None);
  1074.   return Py_None;
  1075. }
  1076.  
  1077. /**** Tkapp Method List ****/
  1078.  
  1079. static PyMethodDef Tkapp_methods[] =
  1080. {
  1081.   {"call", Tkapp_Call},
  1082.   {"globalcall", Tkapp_GlobalCall},
  1083.   {"eval", Tkapp_Eval},
  1084.   {"globaleval", Tkapp_GlobalEval},
  1085.   {"evalfile", Tkapp_EvalFile},
  1086.   {"record", Tkapp_Record},
  1087.   {"adderrorinfo", Tkapp_AddErrorInfo},
  1088.   {"setvar", Tkapp_SetVar},
  1089.   {"globalsetvar", Tkapp_GlobalSetVar},
  1090.   {"getvar", Tkapp_GetVar},
  1091.   {"globalgetvar", Tkapp_GlobalGetVar},
  1092.   {"unsetvar", Tkapp_UnsetVar},
  1093.   {"globalunsetvar", Tkapp_GlobalUnsetVar},
  1094.   {"getint", Tkapp_GetInt},
  1095.   {"getdouble", Tkapp_GetDouble},
  1096.   {"getboolean", Tkapp_GetBoolean},
  1097.   {"exprstring", Tkapp_ExprString},
  1098.   {"exprlong", Tkapp_ExprLong},
  1099.   {"exprdouble", Tkapp_ExprDouble},
  1100.   {"exprboolean", Tkapp_ExprBoolean},
  1101.   {"splitlist", Tkapp_SplitList},
  1102.   {"split", Tkapp_Split},
  1103.   {"merge", Tkapp_Merge},
  1104.   {"createcommand", Tkapp_CreateCommand},
  1105.   {"deletecommand", Tkapp_DeleteCommand},
  1106.   {"createfilehandler", Tkapp_CreateFileHandler},
  1107.   {"deletefilehandler", Tkapp_DeleteFileHandler},
  1108.   {"createtimerhandler", Tkapp_CreateTimerHandler},
  1109.   {"mainloop", Tkapp_MainLoop, 1},
  1110.   {"dooneevent", Tkapp_DoOneEvent, 1},
  1111.   {"quit", Tkapp_Quit},
  1112.   {NULL, NULL}
  1113. };
  1114.  
  1115. /**** Tkapp Type Methods ****/
  1116.  
  1117. static void
  1118. Tkapp_Dealloc (self)
  1119.      PyObject *self;
  1120. {
  1121.   Tk_DestroyWindow (Tkapp_Tkwin (self));
  1122.   Tcl_DeleteInterp (Tkapp_Interp (self));
  1123.   PyMem_DEL (self);
  1124. }
  1125.  
  1126. static PyObject *
  1127. Tkapp_GetAttr (self, name)
  1128.      PyObject *self;
  1129.      char *name;
  1130. {
  1131.   return Py_FindMethod (Tkapp_methods, self, name);
  1132. }
  1133.  
  1134. static PyTypeObject Tkapp_Type =
  1135. {
  1136.   PyObject_HEAD_INIT (&PyType_Type)
  1137.   0,                /*ob_size */
  1138.   "tkapp",            /*tp_name */
  1139.   sizeof (TkappObject),        /*tp_basicsize */
  1140.   0,                /*tp_itemsize */
  1141.   Tkapp_Dealloc,        /*tp_dealloc */
  1142.   0,                /*tp_print */
  1143.   Tkapp_GetAttr,        /*tp_getattr */
  1144.   0,                /*tp_setattr */
  1145.   0,                /*tp_compare */
  1146.   0,                /*tp_repr */
  1147.   0,                /*tp_as_number */
  1148.   0,                /*tp_as_sequence */
  1149.   0,                /*tp_as_mapping */
  1150.   0,                /*tp_hash */
  1151. };
  1152.  
  1153. /**** Tkinter Module ****/
  1154.  
  1155. static PyObject *
  1156. Tkinter_Create (self, args)
  1157.      PyObject *self;
  1158.      PyObject *args;
  1159. {
  1160.   char *screenName = NULL;
  1161.   char *baseName = NULL;
  1162.   char *className = NULL;
  1163.   int interactive = 0;
  1164.  
  1165.   baseName = strrchr (getprogramname (), '/');
  1166.   if (baseName != NULL)
  1167.     baseName++;
  1168.   else
  1169.     baseName = getprogramname ();
  1170.   className = "Tk";
  1171.   
  1172.   if (!PyArg_ParseTuple (args, "|zssi",
  1173.              &screenName, &baseName, &className, &interactive))
  1174.     return NULL;
  1175.  
  1176.   return (PyObject *) Tkapp_New (screenName, baseName, className, 
  1177.                  interactive);
  1178. }
  1179.  
  1180. static PyMethodDef moduleMethods[] =
  1181. {
  1182.   {"create", Tkinter_Create, 1},
  1183.   {"createfilehandler", Tkapp_CreateFileHandler, 0},
  1184.   {"deletefilehandler", Tkapp_DeleteFileHandler, 0},
  1185.   {"createtimerhandler", Tkapp_CreateTimerHandler, 0},
  1186.   {"mainloop", Tkapp_MainLoop, 1},
  1187.   {"dooneevent", Tkapp_DoOneEvent, 1},
  1188.   {"quit", Tkapp_Quit},
  1189.   {NULL, NULL}
  1190. };
  1191.  
  1192. #undef WITH_READLINE /* XXX */
  1193. #ifdef WITH_READLINE
  1194. static int
  1195. EventHook ()
  1196. {
  1197.   if (errorInCmd)        /* XXX Reset tty */
  1198.     {
  1199.       errorInCmd = 0;
  1200.       PyErr_Restore (excInCmd, valInCmd, trbInCmd);
  1201.       excInCmd = valInCmd = trbInCmd = NULL;
  1202.       PyErr_Print ();
  1203.      }
  1204.   if (Tk_GetNumMainWindows() > 0)
  1205.     Tk_DoOneEvent (TK_DONT_WAIT);
  1206.   return 0;
  1207. }
  1208. #endif /* WITH_READLINE */
  1209.  
  1210. static void
  1211. Tkinter_Cleanup ()
  1212. {
  1213. /* This segfault with Tk 4.0 beta and seems unnecessary there as well */
  1214. #if TK_MAJOR_VERSION < 4
  1215.   /* XXX rl_deprep_terminal is static, damned! */
  1216.   while (tkMainWindowList != 0)
  1217.     Tk_DestroyWindow (tkMainWindowList->win);
  1218. #endif
  1219. }
  1220.  
  1221. void
  1222. PyInit_tkinter ()
  1223. {
  1224.   static inited = 0;
  1225.  
  1226. #ifdef WITH_READLINE
  1227.   extern int (*rl_event_hook) ();
  1228. #endif /* WITH_READLINE */
  1229.   PyObject *m, *d, *v;
  1230.  
  1231.   m = Py_InitModule ("tkinter", moduleMethods);
  1232.  
  1233.   d = PyModule_GetDict (m);
  1234.   Tkinter_TclError = Py_BuildValue ("s", "TclError");
  1235.   PyDict_SetItemString (d, "TclError", Tkinter_TclError);
  1236.  
  1237.   v = Py_BuildValue ("i", TK_READABLE);
  1238.   PyDict_SetItemString (d, "READABLE", v);
  1239.   v = Py_BuildValue ("i", TK_WRITABLE);
  1240.   PyDict_SetItemString (d, "WRITABLE", v);
  1241.   v = Py_BuildValue ("i", TK_EXCEPTION);
  1242.   PyDict_SetItemString (d, "EXCEPTION", v);
  1243.   v = Py_BuildValue ("i", TK_X_EVENTS);
  1244.   PyDict_SetItemString (d, "X_EVENTS", v);
  1245.   v = Py_BuildValue ("i", TK_FILE_EVENTS);
  1246.   PyDict_SetItemString (d, "FILE_EVENTS", v);
  1247.   v = Py_BuildValue ("i", TK_TIMER_EVENTS);
  1248.   PyDict_SetItemString (d, "TIMER_EVENTS", v);
  1249.   v = Py_BuildValue ("i", TK_IDLE_EVENTS);
  1250.   PyDict_SetItemString (d, "IDLE_EVENTS", v);
  1251.   v = Py_BuildValue ("i", TK_ALL_EVENTS);
  1252.   PyDict_SetItemString (d, "ALL_EVENTS", v);
  1253.   v = Py_BuildValue ("i", TK_DONT_WAIT);
  1254.   PyDict_SetItemString (d, "DONT_WAIT", v);
  1255.   v = Py_BuildValue ("s", TK_VERSION);
  1256.   PyDict_SetItemString (d, "TK_VERSION", v);
  1257.   v = Py_BuildValue ("s", TCL_VERSION);
  1258.   PyDict_SetItemString (d, "TCL_VERSION", v);
  1259.  
  1260. #ifdef WITH_READLINE
  1261.   rl_event_hook = EventHook;
  1262. #endif /* WITH_READLINE */
  1263.  
  1264.   if (!inited)
  1265.     {
  1266.       inited = 1;
  1267.       if (Py_AtExit (Tkinter_Cleanup) != 0)
  1268.     fprintf(stderr,
  1269.         "Tkinter: warning: cleanup procedure not registered\n");
  1270.     }
  1271.  
  1272.   if (PyErr_Occurred ())
  1273.     Py_FatalError ("can't initialize module tkinter");
  1274. }
  1275.  
  1276. #ifdef macintosh
  1277. void
  1278. panic(char * format, ...)
  1279. {
  1280.     va_list varg;
  1281.     
  1282.     va_start(varg, format);
  1283.     
  1284.     vfprintf(stderr, format, varg);
  1285.     (void) fflush(stderr);
  1286.     
  1287.     va_end(varg);
  1288.  
  1289.     Py_FatalError("Tcl/Tk panic");
  1290. }
  1291.  
  1292. #endif
  1293.